﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MSH.Common.Business;
using NHibernate;
using Facebook;
using NHibernate.Linq;

namespace MSH.Common.Helpers
{
    /// <summary>
    /// De Facebookhelper is verantwoordelijk voor het ophalen van gegevens uit een gekoppeld facebook profiel
    /// </summary>
    public class FacebookHelper
    {
        /// <summary>
        /// Aanvullen van het profiel, met data uit het facebook profiel.
        /// </summary>
        /// <param name="username">Gebruikersnaam</param>
        public static void UpdateFacebookData(string username)
        {
            using (ISession session = NHibernateHelper.GetSessionFactory().OpenSession())
            {
                User user = session.Query<User>().Where(u => u.Username == username)
                    .FirstOrDefault();

                if (user == null)
                    return;

                LogHelper.LogMessage("FacebookProfileTask.UpdateFacebookData(): " + user.Username);

                try
                {
                    UserSocialNetworkAccount facebook = null;
                    foreach (UserSocialNetworkAccount acc in user.UserSocialNetworkAccounts)
                    {
                        if (acc.AccountType.Equals("Facebook"))
                        {
                            facebook = acc;
                            break;
                        }
                    }

                    if (facebook == null)
                        return;

                    FacebookClient client = new FacebookClient(facebook.Token);

                    dynamic me = client.Get("me");

                    String id = me.id;
                    if (!string.IsNullOrEmpty(id))
                        facebook.UniqueAccountId = id;

                    String last_updated = me.updated_time;
                    if (!string.IsNullOrEmpty(last_updated))
                    {
                        DateTime dt = DateTime.Parse(last_updated);

                        if (facebook.LastUpdatedTime != null && dt == facebook.LastUpdatedTime)
                            return;
                        else
                        {
                            facebook.LastUpdatedTime = dt;
                            //user.User.UserSocialNetworkProfileData.Add(CreateFacebookData("last_updated", user.User, me.updated_time));
                        }
                    }

                    List<UserSocialNetworkProfileData> objectsToDelete = new List<UserSocialNetworkProfileData>();
                    foreach (UserSocialNetworkProfileData p in user.UserSocialNetworkProfileData)
                        if (p.AccountType == "Facebook")
                            objectsToDelete.Add(p);

                    user.UserSocialNetworkProfileData.RemoveAll(objectsToDelete);

                    if (!string.IsNullOrEmpty(me.first_name))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("First name", user, me.first_name));
                    if (!string.IsNullOrEmpty(me.last_name))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Last name", user, me.last_name));
                    if (!string.IsNullOrEmpty(me.email))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Email", user, me.email));
                    if (!string.IsNullOrEmpty(me.gender))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Gender", user, me.gender));
                    if (!string.IsNullOrEmpty(me.birthday))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Day of birth", user, me.birthday));
                    if (me.location != null && !string.IsNullOrEmpty(me.location.name))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("City", user, me.location.name));
                    if (!string.IsNullOrEmpty(me.bio))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Biography", user, me.bio));

                    JsonArray education = me.education;
                    List<String> schools = new List<string>();
                    if (education != null)
                    {
                        foreach (dynamic sch in education)
                        {
                            String school = "";
                            if (sch.school != null)
                            {
                                school = sch.school.name;
                            }
                            if (sch.concentration != null)
                            {
                                foreach (dynamic conc in sch.concentration)
                                {
                                    if (string.IsNullOrEmpty(school))
                                        school = conc.name;
                                    else
                                        school = string.Format("{0}, {1}", school, conc.name);
                                }
                            }
                            if (sch.year != null)
                            {
                                if (string.IsNullOrEmpty(school))
                                    school = sch.year.name;
                                else
                                    school = string.Format("{0}, {1}", school, sch.year.name);
                            }
                            if (sch.type != null)
                            {
                                if (string.IsNullOrEmpty(school))
                                    school = sch.type;
                                else
                                    school = string.Format("{0}, {1}", school, sch.type);
                            }
                            schools.Add(school);
                        }
                    }
                    foreach (String s in schools)
                    {
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("School " + (schools.IndexOf(s) + 1), user, s));
                    }

                    JsonArray work = me.work;
                    List<string> workPlaces = new List<string>();
                    if (work != null)
                    {
                        foreach (dynamic wo in work)
                        {
                            string workPlace = "";
                            if (wo.employer != null)
                                workPlace = wo.employer.name;
                            if (wo.location != null)
                            {
                                if (string.IsNullOrEmpty(workPlace))
                                    workPlace = wo.location.name;
                                else
                                    workPlace = string.Format("{0}, {1}", workPlace, wo.location.name);
                            }
                            if (wo.position != null)
                            {
                                if (string.IsNullOrEmpty(workPlace))
                                    workPlace = wo.position.name;
                                else
                                    workPlace = string.Format("{0}, {1}", workPlace, wo.position.name);
                            }
                            workPlaces.Add(workPlace);
                        }
                    }
                    foreach (String w in workPlaces)
                    {
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Work " + (workPlaces.IndexOf(w) + 1), user, w));
                    }

                    JsonArray interested_in = me.interested_in;
                    String interested_in_total = "";
                    if (interested_in != null)
                    {
                        foreach (dynamic interest in interested_in)
                        {
                            if (string.IsNullOrEmpty(interested_in_total))
                                interested_in_total = interest;
                            else
                                interested_in_total = string.Format("{0}, {1}", interested_in_total, interest);
                        }
                    }
                    if (!string.IsNullOrEmpty(interested_in_total))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Interested in", user, interested_in_total));

                    if (!string.IsNullOrEmpty(me.relationship_status))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Relationship status", user, me.relationship_status));
                    if (me.significant_other != null && !string.IsNullOrEmpty(me.significant_other.name))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Significant other", user, me.significant_other.name));
                    if (!string.IsNullOrEmpty(me.political))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Political", user, me.political));
                    if (!string.IsNullOrEmpty(me.religion))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Religion", user, me.religion));
                    if (!string.IsNullOrEmpty(me.website))
                        user.UserSocialNetworkProfileData.Add(CreateFacebookData("Website", user, me.website));

                    using (ITransaction trans = session.BeginTransaction())
                    {
                        session.SaveOrUpdate(user);
                        session.SaveOrUpdate(facebook);
                        trans.Commit();
                    }

                }
                catch (Exception ex)
                {
                    LogHelper.LogMessage("FacebookHelper.UpdateFacebookData(" + user.Username + "): " + ex);
                }
            }
        }

        /// <summary>
        /// Opslaan van de facebook vrienden in de database, zodat deze gebruikt kunnen worden voor vriend suggesties.
        /// </summary>
        /// <param name="username">Gebruikersnaam</param>
        public static void GetFacebookFriends(string username)
        {
            using (ISession session = NHibernateHelper.GetSessionFactory().OpenSession())
            {
                User user = session.Query<User>().Where(u => u.Username == username)
                    .FirstOrDefault();

                if (user == null)
                    return;

                LogHelper.LogMessage("FacebookProfileTask.GetFacebookFriends(): " + user.Username);

                try
                {
                    UserSocialNetworkAccount facebook = null;
                    foreach (UserSocialNetworkAccount acc in user.UserSocialNetworkAccounts)
                    {
                        if (acc.AccountType.Equals("Facebook"))
                        {
                            facebook = acc;
                            break;
                        }
                    }

                    if (facebook == null)
                        return;

                    session.CreateSQLQuery("delete from FacebookFriend where ParentUser = " + user.ID).ExecuteUpdate();

                    FacebookClient client = new FacebookClient(facebook.Token);

                    List<String> facebookFriends = new List<string>();

                    dynamic friends = client.Get("me/friends");

                    if (friends != null)
                    {
                        foreach (dynamic frList in friends.Values)
                        {
                            foreach (dynamic fr in frList)
                            {
                                session.Save(new FacebookFriend() { FriendFbID = fr.id, User = user});
                            }
                        }
                    }

                    using (ITransaction trans = session.BeginTransaction())
                    {
                        trans.Commit();
                    }
                }
                catch (Exception e)
                {
                    LogHelper.LogMessage("FacebookProfileTask.GetFacebookFriends(): " + e);
                    return;
                }
            }
        }

        /// <summary>
        /// Voeg een facebook profiel veld toe aan het profiel.
        /// </summary>
        /// <param name="fieldName">Naam van het veld</param>
        /// <param name="user">Gebruiker</param>
        /// <param name="value">Waarde van het veld</param>
        /// <returns></returns>
        private static UserSocialNetworkProfileData CreateFacebookData(String fieldName, User user, String value)
        {
            return new UserSocialNetworkProfileData()
            {
                AccountType = "Facebook",
                FieldName = fieldName,
                User = user,
                Value = value
            };
        }
    }
}
